﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Mvc;
using System.Web.Routing;
using ActivateYourGlutes.Controllers;
using ActivateYourGlutes.Infrastructure;
using ActivateYourGlutes.Payloads.Home;
using ActivateYourGlutes.Services;
using ActivateYourGlutes.Services.Model;
using NUnit.Framework;
using Rhino.Mocks;

namespace ActivateYourGlutes.Tests.Unit.Controllers
{
    [TestFixture]
    public class Test_HomeController : ControllerTestBase
    {
        private HomeController _controller;
        private IBodyProvider _bodyProvider;
        private IAccountProvider _accountProvider;
        private IGoalProvider _goalProvider;

        // Demo data
        private IEnumerable<Goal> _activeGoals;
        private IEnumerable<Goal> _achievedGoals;
        private IEnumerable<Activity> _recentActivity;
        private Series _primarySeries;
        private Series _secondarySeries;

        [SetUp]
        public override void Init()
        {
            base.Init();

            _recentActivity = new List<Activity>()
                                  {
                                      new Activity()
                                          {
                                              ActivityDate = DateTime.Now,
                                              ActivityId = 1,
                                              Body = null,
                                              Description = "Some activity",
                                              Title = "Activity title"
                                          }
                                  };

            _activeGoals = new List<Goal>()
             {
                 new Goal()
                     {
                         Account = null,
                         AchievedOn = null,
                         Active = true,
                         CreatedOn = new DateTime(1990, 01, 01),
                         DecreaseTo = true,
                         GoalId = 0,
                         TargetDate = null,
                         MeasurementType = _weight,
                         TargetValue = 80
                     }
             };

            _achievedGoals = new List<Goal>()
            {
               new Goal()
                   {
                       Account = null,
                       AchievedOn = new DateTime(2010, 1, 1),
                       Active = true,
                       CreatedOn = new DateTime(2009, 6, 6),
                       DecreaseTo = true,
                       GoalId = 1,
                       MeasurementType = _weight,
                       TargetDate = null,
                       TargetValue = 85
                   }
            };

            _primarySeries = new Series {Title = "Weight"};
            _primarySeries.Values.Add(new SeriesValuePair { XDate = new DateTime(2009, 10, 20), Y = 85});

            _secondarySeries = new Series {Title = "Body Fat"};
            _secondarySeries.Values.Add(new SeriesValuePair {XDate = new DateTime(2010, 1, 5), Y = 15});

            _goalProvider = MockRepository.GenerateStub<IGoalProvider>();
            _bodyProvider = MockRepository.GenerateStub<IBodyProvider>();
            _accountProvider = MockRepository.GenerateStub<IAccountProvider>();
            _controller = new HomeController(_bodyProvider, _accountProvider, _goalProvider, _logger);
            _controller.ControllerContext = new ControllerContext(_httpContext, new RouteData(), _controller);
            _controller.LocaleSettings = _localeSettings;
        }

        [Test]
        public void Test_Index_Get_ReturnsViewAnonymousUser()
        {
            // Arrange

            // Act
            ViewResult result = (ViewResult)_controller.Index();

            // Assert
            Assert.That(result.ViewData["Message"], Is.EqualTo("Welcome to ActivateYourGlutes"));
        }

        [Test]
        public void Test_Index_Get_ReturnsViewNoData()
        {
            // Arrange
            _accountProvider.Stub(ap => ap.CurrentAccount(null)).Return(_mockAccount).IgnoreArguments();
            _accountProvider.Stub(ap => ap.IsDataLoggedForUser(null)).Return(false).IgnoreArguments();

            // Act
            ViewResult result = (ViewResult)_controller.Index();

            // Assert
            IndexPayload payload = (IndexPayload) result.ViewData.Model;
            Assert.That(payload.AccountHasData, Is.False);
            Assert.That(result.ViewData["Message"], Is.EqualTo("Welcome to ActivateYourGlutes"));
        }

        [Test]
        public void Test_Index_Get_ReturnViewForDataPrimaryIndicator()
        {
            // Assert
            _accountProvider.Stub(ap => ap.CurrentAccount(null)).Return(_mockAccount).IgnoreArguments();
            _bodyProvider.Stub(bp => bp.PrimaryIndicatorSeries(null)).Return(_primarySeries).IgnoreArguments();
            _accountProvider.Stub(ap => ap.IsDataLoggedForUser(null)).Return(true).IgnoreArguments();
            _goalProvider.Stub(gp => gp.ActiveGoals(null)).Return(_activeGoals).IgnoreArguments();
            _goalProvider.Stub(gp => gp.RecentlyAchievedGoals(null)).Return(_achievedGoals).IgnoreArguments();
            _accountProvider.Stub(ap => ap.RecentActivity(null)).Return(_recentActivity).IgnoreArguments();
            // specifically set up the account so that it only returns a single primary indicator
            _mockAccount.PrimaryMeasurementType = _weight;
            _mockAccount.SecondaryMeasurementType = null;

            // Act
            ViewResult result = (ViewResult)_controller.Index();

            // Assert
            IndexPayload payload = (IndexPayload)result.ViewData.Model;
            string expectedGraphSeries =
                "<vc:DataSeries LegendText=\"Weight\" RenderAs=\"Line\" AxisYType=\"Primary\" XValueType=\"DateTime\" XValueFormatString=\"d MMM yyyy\" ><vc:DataSeries.DataPoints><vc:DataPoint XValue=\"10/20/2009\" YValue=\"85\" /></vc:DataSeries.DataPoints></vc:DataSeries>";

            Assert.That(payload.AccountHasData, Is.True);
            Assert.That(result.ViewData["Message"], Is.EqualTo("Welcome to ActivateYourGlutes"));
            Assert.That(payload.PrimarySeriesXaml, Is.EqualTo(expectedGraphSeries));
            Assert.That(payload.SecondarySeriesXaml, Is.Null.Or.Empty);
        }

        [Test]
        public void Test_Index_Get_ReturnViewForDataPrimaryAndSecondaryIndicators()
        {
            // Assert
            _accountProvider.Stub(ap => ap.CurrentAccount(null)).Return(_mockAccount).IgnoreArguments();
            _bodyProvider.Stub(bp => bp.PrimaryIndicatorSeries(null)).Return(_primarySeries).IgnoreArguments();
            _bodyProvider.Stub(bp => bp.SecondaryIndicatorSeries(null)).Return(_secondarySeries).IgnoreArguments();
            _accountProvider.Stub(ap => ap.IsDataLoggedForUser(null)).Return(true).IgnoreArguments();
            _goalProvider.Stub(gp => gp.ActiveGoals(null)).Return(_activeGoals).IgnoreArguments();
            _goalProvider.Stub(gp => gp.RecentlyAchievedGoals(null)).Return(_achievedGoals).IgnoreArguments();
            _accountProvider.Stub(ap => ap.RecentActivity(null)).Return(_recentActivity).IgnoreArguments();
            // specifically set up the account so that it only returns a single primary indicator
            _mockAccount.PrimaryMeasurementType = _weight;
            _mockAccount.SecondaryMeasurementType =_bodyFat;

            // Act
            ViewResult result = (ViewResult)_controller.Index();

            // Assert
            IndexPayload payload = (IndexPayload)result.ViewData.Model;
            const string expectedPrimarySeries =
                "<vc:DataSeries LegendText=\"Weight\" RenderAs=\"Line\" AxisYType=\"Primary\" XValueType=\"DateTime\" XValueFormatString=\"d MMM yyyy\" ><vc:DataSeries.DataPoints><vc:DataPoint XValue=\"10/20/2009\" YValue=\"85\" /></vc:DataSeries.DataPoints></vc:DataSeries>";
            const string expectedSecondarySeries = "<vc:DataSeries LegendText=\"Body Fat\" RenderAs=\"Line\" AxisYType=\"Secondary\" XValueType=\"DateTime\" XValueFormatString=\"d MMM yyyy\" ><vc:DataSeries.DataPoints><vc:DataPoint XValue=\"01/05/2010\" YValue=\"15\" /></vc:DataSeries.DataPoints></vc:DataSeries>";
            
            Assert.That(payload.AccountHasData, Is.True);
            Assert.That(result.ViewData["Message"], Is.EqualTo("Welcome to ActivateYourGlutes"));
            Assert.That(payload.PrimarySeriesXaml, Is.EqualTo(expectedPrimarySeries));
            Assert.That(payload.SecondarySeriesXaml, Is.EqualTo(expectedSecondarySeries));
        }

        [Test]
        public void Test_About_Get_ReturnsView()
        {
            // Act
            ViewResult result = (ViewResult) _controller.About();

            // Nothing to assert
        }
    }
}
